package grpcserver

import (
	"context"
	"fmt"
	"gitee.com/go-caipu-team/go-caipu-plugin-sdk/backend"
	"go-caipu/pkg/infra/log"
	"go-caipu/pkg/registry"
	"go-caipu/pkg/services/pluginsintegration/plugincontext"
	"go-caipu/pkg/setting"
	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"
	"net"
)

type Provider interface {
	registry.BackgroundService
	GetServer() *grpc.Server
	GetAddress() string
}

type GPRCServerService struct {
	cfg         *setting.Cfg
	logger      log.Logger
	server      *grpc.Server
	address     string
	provider    *plugincontext.Provider
	startedChan chan struct{}
}

func ProviderService(cfg *setting.Cfg, plugin *plugincontext.Provider) (Provider, error) {
	s := &GPRCServerService{
		cfg:         cfg,
		logger:      log.New("grpc-server"),
		provider:    plugin,
		startedChan: make(chan struct{}),
	}
	var opts []grpc.ServerOption
	//添加安全认证
	opts = append(opts, []grpc.ServerOption{}...)

	s.server = grpc.NewServer(opts...)
	return s, nil
}
func (s *GPRCServerService) Run(ctx context.Context) error {
	s.logger.Info("Running GRPC server", "address", s.cfg.GRPCServerAddress, "network", s.cfg.GRPCServerNetwork, "tls", s.cfg.GRPCServerTLSConfig != nil)
	listener, err := net.Listen(s.cfg.GRPCServerNetwork, s.cfg.GRPCServerAddress)
	if err != nil {
		return fmt.Errorf("GRPC server: failed to listen: %w", err)
	}
	s.address = listener.Addr().String()
	close(s.startedChan)

	serveErr := make(chan error, 1)

	go func() {

		s.logger.Info("GRPC server: starting")
		err := s.server.Serve(listener)
		if err != nil {
			backend.Logger.Error("GRPC server: failed to serve", "err", err)
			serveErr <- err
		}
	}()

	select {
	case err := <-serveErr:
		backend.Logger.Error("GRPC server: failed to serve", "err", err)
		return err
	case <-ctx.Done():
	}
	s.logger.Warn("GRPC server: shutting down")
	// 移除 Stop() 调用，只使用 GracefulStop() 优雅关闭服务器
	s.server.Stop()
	//s.server.GracefulStop()
	return ctx.Err()
}
func (s *GPRCServerService) IsDisabled() bool {
	if s.cfg == nil {
		return true
	}
	return false
}

func (s *GPRCServerService) GetServer() *grpc.Server {
	return s.server
}

func (s *GPRCServerService) GetAddress() string {
	<-s.startedChan
	return s.address
}

// AuthValidToken 验证是否有效token值
func (s *GPRCServerService) AuthValidToken(ctx context.Context, req any, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {

	if !s.cfg.GRPCIsAuth {
		return handler(ctx, req)
	}
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil, fmt.Errorf("GrpcServer missing metadata token")
	}
	plugins := md[backend.GRPCPluginKey]
	if len(plugins) == 0 {
		return nil, fmt.Errorf("GrpcServer missing metadata plugin-id")
	}
	accToken := md[backend.GRPCTokenKey]
	if len(accToken) == 0 {
		return nil, fmt.Errorf("GrpcServer missing metadata accessToken")
	}
	pCtx, exists, _ := s.provider.Get(ctx, plugins[0])
	if !exists {
		return nil, fmt.Errorf(fmt.Sprintf("GrpcServer plugin:%s not found", plugins[0]))
	}
	token := pCtx.AppInstanceSettings.DecryptedSecureJSONData[backend.GRPCTokenKey]
	if token != accToken[0] {
		return nil, fmt.Errorf("GrpcServer accessToken invalid")
	}

	return handler(ctx, req)
}
